/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mobilevikings.app.api;

import com.mobilevikings.app.debugger.DebugFunction;
import com.mobilevikings.app.simbalance.SimBalance;
import com.mobilevikings.app.topuphistory.TopUp;
import com.mobilevikings.util.Utils;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Vector;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpsConnection;
import org.json.me.JSONArray;
import org.json.me.JSONException;
import org.json.me.JSONObject;

/**
 *
 * @author Jeroen
 */
public class ApiConnection {

    private static volatile ApiConnection connection;
    private static String username;
    private static String password;
    private static String format;

    private ApiConnection() {
        username = "";
        password = "";
        format = "json";
    }

    public static ApiConnection getInstance() {
        synchronized (ApiConnection.class) {
            if (connection == null) {
                connection = new ApiConnection();
            }
        }
        return connection;
    }

    /**
     * Sends a API-call to the API-server
     * @param inMethodCall a MethodCall representing the API-call
     * @return a String, representing the answer of the API-server, which you have to convert to an JSONArray or JSONObject
     * @throws java.io.IOException
     * @throws java.lang.SecurityException
     * @throws com.netlog.api.APIError
     * @throws com.netlog.api.InvalidResponseException
     */
    public String send(ApiCall inMethodCall) throws IOException, SecurityException, InvalidResponseException {
        // send request
        String urlString = getApiServer() + inMethodCall.getMethodName() + "." + format;
        System.out.println("  temporary url = " + urlString);
        String response = "";
        urlString += inMethodCall.getArgString();
        System.out.println("  url = " + urlString);
        DebugFunction.log("GET: " + urlString);

        HttpsConnection hc = null;
        InputStream in = null;
        try {
            hc = (HttpsConnection) Connector.open(urlString);
        } catch (IllegalArgumentException ex) {
            ex.printStackTrace();
        }
        System.out.println("  Connection open...");
        hc.setRequestMethod(HttpsConnection.GET);
        hc.setRequestProperty("Authorization", "basic " + Utils.base64encode(username + ":" + password));
        in = hc.openInputStream();
        int contentLength = (int) hc.getLength();
        byte[] data = null;
        DebugFunction.log("LEN = " + contentLength);
        System.out.println("LEN = " + contentLength);
        if (contentLength != -1) {
            data = new byte[contentLength];
            DataInputStream din = new DataInputStream(in);
            din.readFully(data);
        } else {
            // in chunks
            int chunkSize = 32;
            int index = 0;
            int readLength = 0;
            data = new byte[chunkSize];
            readLength = in.read(data, index, chunkSize);
            while (readLength > 0) {
                index += readLength;
                byte[] newData = new byte[index + chunkSize];
                System.arraycopy(data, 0, newData, 0, data.length);
                data = newData;
                readLength = in.read(data, index, chunkSize);
            }
            contentLength = index;

        }

        // Clean up.
        in.close();
        hc.close();

        response = new String(data, 0, contentLength); //data.length te groot

        System.out.print("RESPONSE = " + response);
        return response;
    }

    public SimBalance getSimBalance() throws IOException, InvalidResponseException {
        ApiCall apiCall = new ApiCall("sim_balance");
        String response = send(apiCall);
        JSONObject responseObject = null;
        try {
            responseObject = new JSONObject(response);
        } catch (JSONException ex) {
            throw new InvalidResponseException(ex.getMessage());
        }
        SimBalance balance = new SimBalance();
        try {
            balance.setCredits(responseObject.getDouble("credits"));
            balance.setData(responseObject.getInt("data"));
            balance.setExpirationDate(responseObject.getString("valid_until").substring(0, 10));
            balance.setExpired(responseObject.getBoolean("is_expired"));
            balance.setSms(responseObject.getInt("sms"));
        } catch (JSONException ex) {
            throw new InvalidResponseException(ex.getMessage());
        }
        return balance;

    }

    public Vector getTopUpHistory() throws IOException, InvalidResponseException {
        ApiCall apiCall = new ApiCall("top_up_history");
        String response = send(apiCall);
        JSONArray responseArray = null;

        try {
            responseArray = new JSONArray(response);
        } catch (JSONException ex) {
            throw new InvalidResponseException(ex.getMessage());
        }

        Vector history = new Vector();
        JSONObject jsonTopup = null;
        TopUp topUp = null;
        for (int i = 0; i < responseArray.length(); i++) {
            try {
                jsonTopup = responseArray.getJSONObject(i);
                topUp = new TopUp();
                topUp.setAmount(jsonTopup.getDouble("amount"));
                topUp.setMethod(jsonTopup.getJSONObject("method").getString("pretty"));
                topUp.setDate(jsonTopup.getString("on").replace('T', ' '));

                history.addElement(topUp);
            } catch (JSONException ex) {
                throw new InvalidResponseException(ex.getMessage());
            }

        }

        return history;
    }

    /**
     * @return the username
     */
    public String getUsername() {
        return username;
    }

    /**
     * @param username the username to set
     */
    public void setUsername(String username) {
        ApiConnection.username = username;
    }

    /**
     * @return the password
     */
    public String getPassword() {
        return password;
    }

    /**
     * @param password the password to set
     */
    public void setPassword(String password) {
        ApiConnection.password = password;
    }

    private String getApiServer() {
        return "https://mobilevikings.com/api/1.0/rest/mobilevikings/";
    }
}
